;################
;## RESULTADOS ##
;################
(defmodule modulo-resultados
    (import MAIN ?ALL)
	(import modulo-obtencion ?ALL)
	(import modulo-abstraccion ?ALL)
	(import modulo-asociacion ?ALL)
    (export ?ALL)
)

;# Funcion que se encarga de comparar dos ejercicios
(deffunction comparador-ejercicios (?a ?b)	
	(bind ?c (send ?a get-puntuacionTemporal))
	(bind ?d (send ?b get-puntuacionTemporal))
	(if (eq ?c ?d) then
		(bind ?c (send ?b get-duracionMaxima))
		(bind ?d (send ?a get-duracionMaxima))
	)
	(< ?c ?d)
)

;# Funcion que anade un componente aleatorio para que haya mas variedad de ejercicios
(deffunction incrementar-entropia-ejercicios ($?lista)	
	(loop-for-count (?i 1 (length$ $?lista)) do
		(bind ?puntuacion-actual (send (nth$ ?i $?lista) get-puntuacion))
		(bind ?variacion (mod (random) 10))
		(bind ?puntuacion-nueva (+ ?puntuacion-actual ?variacion))
     	(send (nth$ ?i $?lista) put-puntuacionTemporal ?puntuacion-nueva)
    )
)

(defrule imprimir-solucion
	(declare (salience -10000))	
	(instancia-persona ?persona)
	?r <- (recomendacion (intensidad ?intensidad) (descansos ?descansos) (dificultad ?dificultad-maxima))
	?tipos <- (tipos-ejercicios (lista $?tipos-ejercicios))
	=>
	;(send ?persona imprimir)
	(if (eq ?descansos extra) then
		(bind ?tiempo-entre-descansos 5)
	else
		(bind ?tiempo-entre-descansos 11)
	)
	(printout t crlf "Ejercicios propuestos:" crlf)
	;# Hay que hacer una planificacion para cada dia de la semana teniendo en cuenta el tiempo disponible
	(bind $?lista-tiempo (send ?persona get-tiempoDisponible))
	(bind $?dias-semana (create$ Lunes Martes Miercoles Jueves Viernes Sabado Domingo))
	(loop-for-count (?i 1 (length$ $?lista-tiempo))
		(bind ?tiempo-restante (nth$ ?i $?lista-tiempo))
		;# Solo se hace plan si hay mas de 30 minutos
		(if (>= ?tiempo-restante 3) then
			(bind ?tiempo-seguido 0) ;# Tiempo desde el ultimo descanso
			(seed ?i)
			;# Escogemos un tipo de ejercicio al azar para hacer hoy
			(bind ?azar (+ (mod (random) (length$ $?tipos-ejercicios)) 1))
			(bind ?tipo (nth$ ?azar $?tipos-ejercicios))

			(printout t  crlf "--- " (nth$ ?i $?dias-semana) " (" ?tipo ") " (* ?tiempo-restante 10) "' ----------------------------------------" crlf)

			(bind $?lista-ejercicios-calentamiento (find-all-instances ((?assig Ejercicio)) (member$ Calentamiento ?assig:planificacion)))
			(bind $?lista-ejercicios-desarrollo (find-all-instances ((?assig ?tipo)) (member$ Desarrollo ?assig:planificacion)))
			(bind $?lista-ejercicios-relajacion (find-all-instances ((?assig Ejercicio)) (member$ Relajacion ?assig:planificacion)))
			;# Anadimos ruido para que los ejercicios propuestos varien un poco mas y los ordenamos
			(incrementar-entropia-ejercicios $?lista-ejercicios-calentamiento)
			(incrementar-entropia-ejercicios $?lista-ejercicios-desarrollo)
			(incrementar-entropia-ejercicios $?lista-ejercicios-relajacion)
			(bind $?lista-ejercicios-calentamiento (sort comparador-ejercicios $?lista-ejercicios-calentamiento))
			(bind $?lista-ejercicios-desarrollo (sort comparador-ejercicios $?lista-ejercicios-desarrollo))
			(bind $?lista-ejercicios-relajacion (sort comparador-ejercicios $?lista-ejercicios-relajacion))

			(bind ?j 1)
			(bind ?tiempo-aux 1)
			(bind ?tiempo-restante (- ?tiempo-restante 2))
			(printout t "[Calentamiento]" crlf)
			(while  (and (> ?tiempo-aux 0) (<= ?j (length$ $?lista-ejercicios-calentamiento))) do
				(bind ?candidato (nth$ ?j $?lista-ejercicios-calentamiento))
				(bind ?duracion (send ?candidato get-duracionMinima))
				(if (<= ?duracion ?tiempo-aux) then
					(send (nth$ ?j $?lista-ejercicios-calentamiento) descripcion ?intensidad ?duracion)
					(bind ?tiempo-aux (- ?tiempo-aux ?duracion))
				)
				(bind ?j (+ 1 ?j))
			)

			(bind ?j 1)
			(bind ?o 0)
			(printout t "[Desarrollo]" crlf)
			(while  (and (> ?tiempo-restante 0) (<= ?j (length$ $?lista-ejercicios-desarrollo))) do
				(bind ?candidato (nth$ ?j $?lista-ejercicios-desarrollo))
				(bind ?duracion (send ?candidato get-duracionMaxima))
				(bind ?dificultad (send ?candidato get-dificultad))
				(if (and (<= ?duracion ?tiempo-restante) (or (eq ?dificultad-maxima alta) (< ?dificultad 5))) then
					(send (nth$ ?j $?lista-ejercicios-desarrollo) descripcion ?intensidad ?duracion)
					;# Debug (send (nth$ ?j $?lista-ejercicios-desarrollo) imprimir)
					(bind ?o 1)
					(bind ?tiempo-restante (- ?tiempo-restante ?duracion))
					(bind ?tiempo-seguido (+ ?tiempo-seguido ?duracion))
				)
				(if (and (>= ?tiempo-seguido ?tiempo-entre-descansos) (>= ?tiempo-restante 2)) then
					(printout t "    Descanso, 10'" crlf)
					(bind ?tiempo-restante (- ?tiempo-restante 1))
					(bind ?tiempo-seguido 0)
				)
				(bind ?j (+ 1 ?j))
				(if (and (> ?j (length$ $?lista-ejercicios-desarrollo)) (> ?o 0)) then
					(bind ?o 0) (bind ?j 1))
			)

			(bind ?j 1)
			(bind ?tiempo-aux 1)
			(printout t "[Relajacion]" crlf)
			(while  (and (> ?tiempo-aux 0) (<= ?j (length$ $?lista-ejercicios-relajacion))) do
				(bind ?candidato (nth$ ?j $?lista-ejercicios-relajacion))
				(bind ?duracion (send ?candidato get-duracionMinima))
				(if (<= ?duracion ?tiempo-aux) then
					(send (nth$ ?j $?lista-ejercicios-relajacion) descripcion ?intensidad ?duracion)
					;# Debug (send (nth$ ?j $?lista-ejercicios-relajacion) imprimir)
					(bind ?tiempo-aux (- ?tiempo-aux ?duracion))
				)

				(bind ?j (+ 1 ?j))
			)
		)
	)
	(assert (final))
)
